/*
 * @Author: xiaosihan 
 * @Date: 2023-02-16 00:22:31 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2023-02-16 19:08:55
 */

import { last } from "lodash";
import { BufferAttribute, Euler, Line, LineBasicMaterial, Object3D, Vector3 } from "three";
import threeUtils from "./threeUtils";


// 关键帧类型
export type Keyframe = {
    position: Vector3;
    scale: Vector3;
    rotation: Euler;
    timeTemp: number; //时间节点 单位毫秒.
}


export type KeyframeAnimationProps = {
    speedScale?: number; // 速度调整
    object3d: Object3D; // 需要移动的对象
    keyframes: Array<Keyframe>,
}

// 关键帧动画对象
export default class KeyframeAnimation extends Object3D {

    constructor(props: KeyframeAnimationProps) {
        super();

        // 速度调整
        this.speedScale = props.speedScale || 1;

        // 设置关键帧对象数组
        this.setKeyframes(props.keyframes);


        // 设置对象
        this.setObject3D(props.object3d);

    }

    // 速度调整
    speedScale = 1;

    // 需要需要移动的对象
    object3d!: Object3D;

    //路径辅助线
    halperLine = new Line(undefined, new LineBasicMaterial({ color: "#f00" }));

    // 关键帧数组
    keyframes: Array<Keyframe> = [];

    // 设置需要移动的对象
    setObject3D(object3d: Object3D) {
        this.object3d = object3d;
        if (threeUtils.isDev) {
            this.children = [object3d, this.halperLine];
        } else {
            this.children = [object3d];
        }
    }

    // 获取单个关键帧
    getKeyframe(i: number) {
        return this.keyframes[i];
    }

    // 设置单个关键帧
    setKeyframe(i: number, keyframe: Keyframe) {
        this.keyframes[i] = keyframe;
        this.setKeyframes(this.keyframes);
    }

    //设置全部关键帧
    setKeyframes(keyframes: Array<Keyframe>) {
        this.keyframes = keyframes;
        const position: Array<number> = [];
        keyframes.map(k => {
            position.push(k.position.x);
            position.push(k.position.y);
            position.push(k.position.z);
        });
        this.halperLine.geometry.setAttribute("position", new BufferAttribute(new Float32Array(position), 3, false));
    }

    // 更具关键帧的信息更新 对象的位置
    update() {
        const { _timeTemp } = threeUtils;
        const maxtimetemp = last(this.keyframes)!.timeTemp;
        const currentTime = _timeTemp % maxtimetemp;

        const currentKeyframeIndex = this.keyframes.findIndex(k => currentTime < k.timeTemp);

        const startKeyframe = this.keyframes[currentKeyframeIndex - 1];
        const endKeyframe = this.keyframes[currentKeyframeIndex];
        const progress = (currentTime - startKeyframe.timeTemp) / (endKeyframe.timeTemp - startKeyframe.timeTemp);

        this.object3d.position.copy(endKeyframe.position).sub(startKeyframe.position).multiplyScalar(progress).add(startKeyframe.position);
        this.object3d.scale.copy(endKeyframe.scale).sub(startKeyframe.scale).multiplyScalar(progress).add(startKeyframe.scale);

        this.object3d.rotation.set(
            (endKeyframe.rotation.x - startKeyframe.rotation.x) * progress + startKeyframe.rotation.x,
            (endKeyframe.rotation.y - startKeyframe.rotation.y) * progress + startKeyframe.rotation.y,
            (endKeyframe.rotation.z - startKeyframe.rotation.z) * progress + startKeyframe.rotation.z,
        );

        this.dispatchEvent({ type: "update" } as never);
    }

    //更新关键帧的实例矩阵
    updateMatrix(): void {
        this.update();
        super.updateMatrix();
    }


}